"""
配置文件管理模块
"""
import os
import yaml
from pathlib import Path
from typing import List, Dict, Optional
from i18n import t


class _IndentDumper(yaml.SafeDumper):
    """Custom dumper to indent sequence items (e.g. repos list)."""

    def increase_indent(self, flow=False, indentless=False):
        return super().increase_indent(flow, False)


class Config:
    """配置管理类"""
    
    DEFAULT_GLOBAL_CONFIG = {
        "repos": [
            "cangjie_compiler",
            "cangjie_runtime",
            "cangjie_tools",
            "cangjie_stdx",
            "llvm-project",
            "cangjie_test",
            "cangjie_test_framework",
            "cangjie_multiplatform_interop",
            "cangjie_docs",
            "cangjie_python_interop"
        ],
        "base_org": "Cangjie",
        "base_url": "https://gitcode.com/Cangjie",
        "default_branch": "main",
        "language": "zh",
    }
    
    DEFAULT_PROJECT_CONFIG = {
        "branch": "main",
        "base_branch": None,  # PR 目标分支，如果为 None 则使用 default_branch
        "gitcode_username": None,
        "repos": None  # None 表示使用全局配置的仓库列表
    }
    
    def __init__(self, config_path: Optional[str] = None):
        """
        初始化配置
        :param config_path: 配置文件路径，如果为 None，会加载全局和项目配置
        """
        # 全局配置路径
        self.global_config_path = Path(os.path.expanduser("~/.cjdev.yaml"))
        
        # 如果指定了 config_path，使用指定的路径（向后兼容）
        if config_path:
            self.config_path = Path(config_path)
            # 向后兼容模式：workspace 使用当前目录
            self.workspace = Path(os.getcwd())
            self.project_config_path = self.workspace / ".cjdev.yaml"
            self.config = self._load_config()
        else:
            # 查找项目根目录（向上查找 .cjdev.yaml）
            self.workspace = self._find_project_root()
            self.project_config_path = self.workspace / ".cjdev.yaml"
            # 加载全局和项目配置
            self.config = self._load_merged_config()
    
    def _find_project_root(self) -> Path:
        """
        查找项目根目录（优先使用当前目录，如果当前目录有 .cjdev.yaml）
        否则向上查找 .cjdev.yaml 文件
        如果找不到，返回当前目录
        """
        current = Path(os.getcwd()).resolve()
        
        # 优先检查当前目录是否有 .cjdev.yaml
        current_config = current / ".cjdev.yaml"
        if current_config.exists():
            return current
        
        # 向上查找 .cjdev.yaml 文件
        for path in current.parents:
            config_file = path / ".cjdev.yaml"
            if config_file.exists():
                return path
        
        # 如果找不到，返回当前目录
        return current
    
    def _load_merged_config(self) -> Dict:
        """加载合并的配置（全局 + 项目）"""
        # 先加载全局配置
        global_config = self._load_config_file(self.global_config_path, self.DEFAULT_GLOBAL_CONFIG)
        
        # 再加载项目配置（如果存在）
        project_config = {}
        if self.project_config_path.exists():
            project_config = self._load_config_file(self.project_config_path, self.DEFAULT_PROJECT_CONFIG)
        
        # 合并配置（项目配置覆盖全局配置）
        merged = self.DEFAULT_GLOBAL_CONFIG.copy()
        merged.update(global_config)
        merged.update(project_config)
        
        return merged
    
    def _load_config_file(self, config_path: Path, default_config: Dict) -> Dict:
        """加载单个配置文件"""
        if config_path.exists():
            try:
                with open(config_path, 'r', encoding='utf-8') as f:
                    config = yaml.safe_load(f) or {}
                return config
            except Exception as e:
                print(t("config.warning_failed_to_load_config_from", path=config_path, error=e))
                return default_config.copy()
        return default_config.copy()
    
    def _load_config(self) -> Dict:
        """加载配置文件（向后兼容）"""
        if self.config_path.exists():
            try:
                with open(self.config_path, 'r', encoding='utf-8') as f:
                    config = yaml.safe_load(f) or {}
                # 合并默认配置
                merged = self.DEFAULT_GLOBAL_CONFIG.copy()
                merged.update(config)
                return merged
            except Exception as e:
                print(t("config.warning_failed_to_load_config_from", path=self.config_path, error=e))
                return self.DEFAULT_GLOBAL_CONFIG.copy()
        else:
            # 创建默认配置文件
            self._save_config(self.DEFAULT_GLOBAL_CONFIG)
            return self.DEFAULT_GLOBAL_CONFIG.copy()
    
    def _save_config(self, config: Dict):
        """保存配置文件（向后兼容）"""
        try:
            self.config_path.parent.mkdir(parents=True, exist_ok=True)
            with open(self.config_path, 'w', encoding='utf-8') as f:
                yaml.dump(
                    config,
                    f,
                    allow_unicode=True,
                    default_flow_style=False,
                    sort_keys=False,
                    Dumper=_IndentDumper,
                )
        except Exception as e:
            print(t("config.warning_failed_to_save_config_to", path=self.config_path, error=e))
    
    def save_project_config(self, **kwargs):
        """保存项目配置（工作目录下的 .cjdev.yaml）"""
        try:
            # 加载现有项目配置
            project_config = {}
            if self.project_config_path.exists():
                project_config = self._load_config_file(self.project_config_path, self.DEFAULT_PROJECT_CONFIG)
            
            # 更新配置
            project_config.update(kwargs)
            
            # 保存
            self.project_config_path.parent.mkdir(parents=True, exist_ok=True)
            with open(self.project_config_path, 'w', encoding='utf-8') as f:
                yaml.dump(
                    project_config,
                    f,
                    allow_unicode=True,
                    default_flow_style=False,
                    sort_keys=False,
                    Dumper=_IndentDumper,
                )
            
            # 更新内存中的配置
            self.config.update(project_config)
        except Exception as e:
            print(t("config.warning_failed_to_save_project_config", path=self.project_config_path, error=e))
    
    def get_repos(self) -> List[str]:
        """获取仓库列表（优先使用项目配置，否则使用全局配置）"""
        # 先检查项目配置中是否有仓库列表
        if self.project_config_path.exists():
            try:
                project_config = self._load_config_file(self.project_config_path, self.DEFAULT_PROJECT_CONFIG)
                if project_config.get("repos") is not None:
                    return project_config.get("repos", [])
            except:
                pass
        
        # 使用全局配置的仓库列表
        return self.config.get("repos", [])
    
    def get_base_org(self) -> str:
        """获取基础组织名"""
        return self.config.get("base_org", "Cangjie")
    
    def get_base_url(self) -> str:
        """获取基础 URL"""
        return self.config.get("base_url", "https://gitcode.com/Cangjie")
    
    def get_default_branch(self) -> str:
        """获取默认分支（全局配置）"""
        return self.config.get("default_branch", "main")
    
    def get_branch(self) -> str:
        """获取当前分支（项目配置，如果没有则使用默认分支）"""
        return self.config.get("branch") or self.get_default_branch()
    
    def get_base_branch(self) -> str:
        """获取 base 分支（PR 目标分支，项目配置优先，如果没有则使用默认分支）"""
        base_branch = self.config.get("base_branch")
        if base_branch:
            return base_branch
        return self.get_default_branch()
    
    def get_workspace(self) -> str:
        """获取工作目录（项目根目录）"""
        # 直接返回找到的项目根目录
        return str(self.workspace)
    
    def get_gitcode_username(self) -> str:
        """获取 GitCode 用户名（项目配置）"""
        return self.config.get("gitcode_username")

    def get_language(self) -> str:
        """获取当前界面语言，默认为中文"""
        return self.config.get("language", "zh")

    def has_language_config(self) -> bool:
        """检查全局配置中是否显式设置了语言 / Check if global config explicitly sets language"""
        if not self.global_config_path.exists():
            return False
        try:
            with open(self.global_config_path, "r", encoding="utf-8") as f:
                current = yaml.safe_load(f) or {}
            lang = current.get("language")
            return lang in ("zh", "en")
        except Exception:
            return False

    def set_language(self, language: str):
        """更新全局配置中的语言"""
        if language not in ("zh", "en"):
            language = "zh"
        global_config = self._load_config_file(self.global_config_path, self.DEFAULT_GLOBAL_CONFIG)
        global_config["language"] = language
        try:
            self.global_config_path.parent.mkdir(parents=True, exist_ok=True)
            with open(self.global_config_path, 'w', encoding='utf-8') as f:
                yaml.dump(
                    global_config,
                    f,
                    allow_unicode=True,
                    default_flow_style=False,
                    sort_keys=False,
                    Dumper=_IndentDumper,
                )
            self.config["language"] = language
        except Exception as e:
            print(t("config.warning_failed_to_update_language_in", error=e))
    
    def get_repo_url(self, repo: str, username: str = None) -> str:
        """
        获取仓库 URL
        :param repo: 仓库名
        :param username: 用户名，如果提供则从该用户的 fork 仓获取，否则从主仓获取
        """
        if username:
            return f"https://gitcode.com/{username}/{repo}.git"
        return f"{self.get_base_url()}/{repo}.git"
    
    def update_config(self, **kwargs):
        """更新配置（向后兼容，更新全局配置）"""
        self.config.update(kwargs)
        self._save_config(self.config)
    
    def add_repos(self, repos: List[str]):
        """
        添加仓库到配置（更新全局配置）
        :param repos: 仓库名列表
        """
        current_repos = set(self.get_repos())
        new_repos = [r for r in repos if r not in current_repos]
        if new_repos:
            updated_repos = self.get_repos() + new_repos
            # 更新全局配置
            global_config = self._load_config_file(self.global_config_path, self.DEFAULT_GLOBAL_CONFIG)
            global_config["repos"] = updated_repos
            try:
                self.global_config_path.parent.mkdir(parents=True, exist_ok=True)
                with open(self.global_config_path, 'w', encoding='utf-8') as f:
                    yaml.dump(
                        global_config,
                        f,
                        allow_unicode=True,
                        default_flow_style=False,
                        sort_keys=False,
                        Dumper=_IndentDumper,
                    )
                self.config["repos"] = updated_repos
            except Exception as e:
                print(t("config.warning_failed_to_save_global_config", error=e))
            return new_repos
        return []
    
    def remove_repos(self, repos: List[str]):
        """
        从配置中移除仓库（更新全局配置）
        :param repos: 仓库名列表
        """
        current_repos = self.get_repos()
        removed_repos = [r for r in repos if r in current_repos]
        if removed_repos:
            updated_repos = [r for r in current_repos if r not in removed_repos]
            # 更新全局配置
            global_config = self._load_config_file(self.global_config_path, self.DEFAULT_GLOBAL_CONFIG)
            global_config["repos"] = updated_repos
            try:
                self.global_config_path.parent.mkdir(parents=True, exist_ok=True)
                with open(self.global_config_path, 'w', encoding='utf-8') as f:
                    yaml.dump(
                        global_config,
                        f,
                        allow_unicode=True,
                        default_flow_style=False,
                        sort_keys=False,
                        Dumper=_IndentDumper,
                    )
                self.config["repos"] = updated_repos
            except Exception as e:
                print(t("config.warning_failed_to_save_global_config", error=e))
            return removed_repos
        return []

